package stardust.product.platform.webc.spi.servlet;


import java.util.Map;
import java.util.Properties;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import stardust.product.platform.webc.RenderForward;
import stardust.product.platform.webc.RenderHandle;
import stardust.product.platform.webc.WebcConfig;
import stardust.product.platform.webc.WebcException;
import stardust.product.platform.webc.WebcRequestHandler;
import stardust.product.platform.webc.WebcResourceReference;
import com.sun.xml.internal.messaging.saaj.util.ByteInputStream;


public class VelocityRenderer implements RenderHandle
{
  
  private VelocityEngine velocityEngine;
  
  private void initialize(String config, String baseDir) throws Exception
  {
    this.velocityEngine = new VelocityEngine();
    
    Properties p = new Properties();
    p.load(new ByteInputStream(config.getBytes(), config.getBytes().length));
    
    if (!p.containsKey(Velocity.FILE_RESOURCE_LOADER_PATH))
    {
      this.velocityEngine.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, baseDir);
    }
    
    this.velocityEngine.init(p);
  }

  public void render(WebcRequestHandler request, WebcResourceReference reference, String uri, RenderForward forward)
  {
    ServletWebcRequestHandler req = (ServletWebcRequestHandler) request;
    String returnPath = forward.getResultPath();
    
    if (returnPath == null || returnPath.isEmpty())
    {
      return;
    }
    
    try
    {
      if (returnPath.indexOf(':') != -1)
      {
        String jumpType = returnPath.substring(0, returnPath.indexOf(':')).trim();
        String jumpUri = returnPath.substring(returnPath.indexOf(':') + 1).trim();
        
        if (!jumpType.equalsIgnoreCase("redirect"))
        {
          /*
           * 计算追加前导和后缀。
           */
          String prefix = request.getWebcContext().getConfig().getParameter().get(WebcConfig.CFG_PATH_PREFIX);
          String suffix = request.getWebcContext().getConfig().getParameter().get(WebcConfig.CFG_PATH_SUFFIX);
          
          if (prefix != null)
          {
            prefix = prefix.replace('\\', '/');
            prefix = prefix.endsWith("/") ? prefix.substring(0, prefix.length() - 1) : prefix;
            jumpUri = jumpUri.startsWith("/") ? jumpUri : "/" + jumpUri;
            jumpUri = prefix + jumpUri;
          }
          if (suffix != null)
          {
            suffix = suffix.replace('\\', '/');
            jumpUri = jumpUri + suffix;
          }
        }
        
        if (jumpType.equalsIgnoreCase("redirect"))
        {
          req.getResponse().sendRedirect(jumpUri);
          return;
        }
      }
      
      if (this.velocityEngine == null)
      {
        this.initialize(request.getWebcContext().getConfig().getParameter().get(WebcConfig.CFG_VELOCITY_CONFIG), req.getRequest().getSession().getServletContext().getRealPath("/"));
      }
      
      /*
       * 计算追加前导和后缀。
       */
      String prefix = request.getWebcContext().getConfig().getParameter().get(WebcConfig.CFG_PATH_PREFIX);
      String suffix = request.getWebcContext().getConfig().getParameter().get(WebcConfig.CFG_PATH_SUFFIX);
      
      if (prefix != null)
      {
        prefix = prefix.replace('\\', '/');
        prefix = prefix.endsWith("/") ? prefix.substring(0, prefix.length() - 1) : prefix;
        returnPath = returnPath.startsWith("/") ? returnPath : "/" + returnPath;
        returnPath = prefix + returnPath;
      }
      if (suffix != null)
      {
        suffix = suffix.replace('\\', '/');
        returnPath = returnPath + suffix;
      }

      Map<String, Object> context = req.getUtils();
      context.put("result", forward.getResult());
      
      VelocityContext ctx = new VelocityContext();
      ctx.put("webc", context);
      this.velocityEngine.getTemplate(returnPath).merge(ctx, req.getResponse().getWriter());
    }
    catch(Exception e)
    {
      throw new WebcException("访问资源[" + uri + " -> " + reference.getUri() + "]时发生错误，调用处理程序成功，但执行渲染失败。", e);
    }
  }

}
